﻿using Microsoft.EntityFrameworkCore;
using net_work.Common;
using net_work.Config.DataBaseConfig.Sys;
using net_work.Data.Entity;
using net_work.Data.Entity.Appr;
using net_work.Data.Entity.Cam;
using net_work.Data.Entity.Cou;
using net_work.Data.Entity.Hmw;
using net_work.Data.Entity.Sys;
using net_work.Data.Entity.System;

namespace net_work.Config;

public class ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IUserContext userContext)
    : DbContext(options)
{
    // 数据库表
    /// <summary>
    /// 用户表
    /// </summary>
    public DbSet<User> Users { get; set; }

    /// <summary>
    /// 个人表
    /// </summary>
    public DbSet<Person> People { get; set; }

    /// <summary>
    /// 学院表
    /// </summary>
    public DbSet<College> Colleges { get; set; }

    /// <summary>
    /// 教师表
    /// </summary>
    public DbSet<Teacher> Teachers { get; set; }

    /// <summary>
    /// 管理班级表
    /// </summary>
    public DbSet<AdministrativeClass> AdministrativeClasses { get; set; }

    /// <summary>
    /// 部门表
    /// </summary>
    public DbSet<Department> Departments { get; set; }

    /// <summary>
    /// 学生表
    /// </summary>
    public DbSet<Student> Students { get; set; }

    /// <summary>
    /// 课程表
    /// </summary>
    public DbSet<Course> Courses { get; set; }

    /// <summary>
    /// 教学表
    /// </summary>
    public DbSet<Teaching> Teachings { get; set; }

    /// <summary>
    /// 排课表
    /// </summary>
    public DbSet<Schedule> Schedules { get; set; }

    /// <summary>
    /// 教师授课表
    /// </summary>
    public DbSet<TeacherTeaching> TeacherTeachings { get; set; }

    /// <summary>
    /// 选课表
    /// </summary>
    public DbSet<Enrollment> Enrollments { get; set; }

    /// <summary>
    /// 题库表
    /// </summary>
    public DbSet<BankQuestion> BankQuestions { get; set; }

    /// <summary>
    /// 题库答案表
    /// </summary>
    public DbSet<BankAnswer> BankAnswers { get; set; }

    /// <summary>
    /// 作业表
    /// </summary>
    public DbSet<Homework> Homeworks { get; set; }

    /// <summary>
    /// 作业题目表
    /// </summary>
    public DbSet<HomeworkQuestion> HomeworkQuestions { get; set; }

    /// <summary>
    /// 学生提交答案表
    /// </summary>
    public DbSet<QuestionAnswerSubmission> QuestionAnswerSubmissions { get; set; }

    /// <summary>
    /// 文件使用表
    /// </summary>
    public DbSet<FileUse> FileUses { get; set; }

    /// <summary>
    /// 文件表
    /// </summary>
    public DbSet<MyFile> MyFiles { get; set; }

    /// <summary>
    /// 消息表
    /// </summary>
    public DbSet<Message> Messages { get; set; }

    /// <summary>
    /// 申请表
    /// </summary>
    public DbSet<Apply> Applies { get; set; }

    /// <summary>
    /// 流程表
    /// </summary>
    public DbSet<Flow> Flows { get; set; }

    /// <summary>
    /// 流程节点表
    /// </summary>
    public DbSet<FlowNode> FlowNodes { get; set; }

    /// <summary>
    /// 审批实例表
    /// </summary>
    public DbSet<ApprovalInstance> ApprovalInstances { get; set; }

    /// <summary>
    /// 审批实例历史表
    /// </summary>
    public DbSet<ApprovalInstanceHistory> ApprovalInstanceHistories { get; set; }

    /// <summary>
    /// 配置模型映射和全局查询过滤器
    /// </summary>
    /// <param name="modelBuilder"></param>
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // 获取命名空间
        var assembly = typeof(UserEntityTypeConfiguration).Assembly;

        // 查找所有实现了 IEntityTypeConfiguration<T> 的类
        var configurationTypes = assembly.GetTypes()
            .Where(t => t.GetInterfaces()
                .Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>)));

        foreach (var type in configurationTypes)
        {
            // 创建配置类实例
            var configurationInstance = Activator.CreateInstance(type);

            // 获取配置类的实体类型
            var entityType = type.GetInterfaces()
                .First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>))
                .GetGenericArguments()[0];

            // 调用 ApplyConfiguration 方法
            var method = typeof(ModelBuilder)
                .GetMethod(nameof(ModelBuilder.ApplyConfiguration))!
                .MakeGenericMethod(entityType);

            method.Invoke(modelBuilder, new[] { configurationInstance });
        }

        // 全局查询过滤器（适用于所有继承 BaseEntity 的表）
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        {
            // 检查是否继承 BaseEntity
            if (!typeof(BaseEntity).IsAssignableFrom(entityType.ClrType))
            {
                continue;
            }

            var method = typeof(ApplicationDbContext)
                .GetMethod(nameof(SetGlobalQueryFilter),
                    System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)
                ?.MakeGenericMethod(entityType.ClrType);

            method?.Invoke(null, [modelBuilder]);
        }
    }

    /// <summary>
    /// 重写 SaveChangesAsync 实现公共字段自动填充
    /// </summary>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        var entries = ChangeTracker.Entries<BaseEntity>();

        foreach (var entry in entries)
        {
            if (entry.State == EntityState.Added)
            {
                // 自动填充创建字段
                entry.Entity.CreatedBy = userContext.Username;
                entry.Entity.CreatedTime = DateTime.UtcNow.ToLocalTime();

                // 同时设置更新时间
                entry.Entity.UpdatedBy = userContext.Username;
                entry.Entity.UpdatedTime = DateTime.UtcNow.ToLocalTime();
            }
            else if (entry.State == EntityState.Modified)
            {
                // 自动填充更新字段
                entry.Entity.UpdatedBy = userContext.Username;
                entry.Entity.UpdatedTime = DateTime.UtcNow.ToLocalTime();
            }
        }

        return base.SaveChangesAsync(cancellationToken);
    }

    /// <summary>
    /// 全局查询过滤器
    /// </summary>
    private static void SetGlobalQueryFilter<T>(ModelBuilder modelBuilder) where T : BaseEntity
    {
        modelBuilder.Entity<T>().HasQueryFilter(e => e.DelFlag == '0'); // 仅查询未删除的数据
    }
}